// vue3 改 defineProperty 为 proxy

debugger;
class Dep {
  // 放着所有要被触发的函数
  constructor() {
    this.effects = new Set();
  }

  //   把effect放进队列
  depend() {
    if (activeEffect) {
      this.effects.add(activeEffect);
    }
  }

  //   触发
  notify() {
    this.effects.forEach((effect) => {
      effect();
    });
  }
}

// watchEffect 调用一次（同时把节点绑定get和set）
let activeEffect = null;
function watchEffect(effect) {
  activeEffect = effect;
  //   这里面调用了一次effect 所以 definexxx的get方法被调用了 ,进而将依赖放进对应的队列了
  effect();
  activeEffect = null;
}

/**
 * @author lwt
 * @param { Object } target
 * @param { object | string | number... } key
 * @returns { Dep }
 */
let targetMap = new WeakMap();
function getDep(target, key) {
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }

  let dep = depsMap.get(key);
  if (!dep) {
    dep = new Dep();
    depsMap.set(key, dep);
  }
  return dep;
}

/**
 * @author lwt
 * @param { object } row
 * @returns { object }
 */
function reactive(row) {
  return new Proxy(row, {
    get(target, key) {
      const dep = getDep(target, key);
      dep.depend();
      return target[key];
    },
    set(target, key, newVal) {
      const dep = getDep(target, key);
      target[key] = newVal;
      dep.notify();
    },
  });
}

// 绑定row.info和对应的dep,同时绑定defineProperty到info
let row = reactive({
  info: "我是响应式数据",
  age: 1,
  height: 100,
});

let b;
// 收集effect函数,同时触发一次（再次强调 该次触发是因为被get找到然后depend进去的）
watchEffect(function () {
  b = row.age;
  console.log("row响应age", b);
});
watchEffect(function () {
  b = row.height;
  console.log("row响应height", b);
});
row.age = 2;
row.height = 200;
